<html>
<body>
<script src="resources/fs-test-util.js"></script>
<div>This tests basic cross-filesystem operations.</div>

<div id="destination" style="min-height:100px; border: solid 1px black">Drop files here if you test this manually</div>

<div id="console"></div>

<script>
var methods = [ 'copyTo', 'moveTo' ];
var sourceTestDirectory, destTestDirectory;

var destDirectoryPath = '/test';
var sourceDirectoryPath = '../../editing/pasteboard/resources';

// Actual files in the sourceDirectoryPath.
var testFiles = [
    { path:'apple.gif' },
    { path:'mozilla.gif' },
    { path:'drop-file-svg.svg' },
    { path:'copy-backslash-euc.html' },
    { path:'test_directory', directory:true },
    { path:'test_directory/test.txt' }
];

// Note: for now we don't run moveTo test since drag-and-drop isolated
// filesystem, which we use for source filesystem, is read-only.
// FIXME: allow writing to PERSISTENT filesystem without quota error in
// DumpRenderTree so that we can test TEMPORARY <-> PERSISTENT cross operation
// checks.
var tests = [
    testCopyFile,
    testCopyDirectory,
];

function log(text)
{
    var console = document.getElementById('console');
    console.appendChild(document.createTextNode(text));
    console.appendChild(document.createElement('br'));
}

function test(expect, actual)
{
    log((expect == actual ? 'PASS' : 'FAIL') + ': "' + expect + '" == "' + actual + '"');
}


function errorCallback(msg)
{
    return function(e) {
        console.log(e);
        log('ERROR:' + msg + ': ' + e.name);
        if (window.testRunner)
            testRunner.notifyDone();
    };
}

function setupDestFileSystem(successCallback) {
    webkitRequestFileSystem(window.TEMPORARY, 1024, function (fs) {
        removeAllInDirectory(fs.root, function() {
            fs.root.getDirectory(
                destDirectoryPath,
                {create:true},
                function (entry) {
                    destTestDirectory = entry;
                    successCallback();
                },
              errorCallback(`dest: createDirectory(${destDirectoryPath})`));
          }, errorCallback('dest: removeAllInDirectory'));
    }, errorCallback('dest: requestFileSystem for PERSISTENT'));
}

function runTests(index, successCallback) {
    if (index >= tests.length) {
        successCallback();
        return;
    }
    var next = function() { runTests(index + 1, successCallback); };
    resetDirectory(destTestDirectory, function() { tests[index](next); });
}

function testCopyFile(successCallback) {
    testOnFile(0, 'copyTo', successCallback);
}

function testCopyDirectory(successCallback) {
    testOnDirectory(0, 'copyTo', successCallback);
}

function testOnFile(index, method, successCallback) {
    if (index >= testFiles.length) {
        successCallback();
        return;
    }
    var next = function() { testOnFile(index + 1, method, successCallback); };
    if (testFiles[index].directory) {
        next();
        return;
    }
    var file = testFiles[index];
    log('Testing ' + method + ' ' + file.path + ': ' + sourceTestDirectory.fullPath + ' => ' + destTestDirectory.fullPath);
    sourceTestDirectory.getFile(
        file.path, {create:false}, function(source) {
            source[method](destTestDirectory, '', function(dest) {
                verifyFile(source, dest, next);
            }, errorCallback('testOnFile: ' + method + ':' + file.path));
        }, errorCallback('testOnFile: getFile:' + file.path));
}

function testOnDirectory(index, method, successCallback) {
    if (index >= testFiles.length) {
        successCallback();
        return;
    }
    var next = function() { testOnFile(index + 1, method, successCallback); };
    if (!testFiles[index].directory) {
        next();
        return;
    }
    var file = testFiles[index];
    log('Testing ' + method + ' ' + file.path + ': ' + sourceTestDirectory.fullPath + ' => ' + destTestDirectory.fullPath);
    sourceTestDirectory.getDirectory(
        file.path, {create:false}, function(source) {
            source[method](destTestDirectory, '', function(dest) {
                verifyFile(source, dest, next);
            }, errorCallback('testOnDirectory: ' + method + ':' + file.path));
        }, errorCallback('testOnDirectory: getDirectory:' + file.path));
}

function verifyFile(source, dest, successCallback) {
    test(source.name, dest.name);
    source.getMetadata(function(sourceMetadata) {
        var expectedSize = sourceMetadata.size;
        dest.getMetadata(function(destMetadata) {
            test(expectedSize, destMetadata.size);
            successCallback();
        }, errorCallback('getMetadata:' + dest.fullPath));
    }, errorCallback('getMetadata:' + source.fullPath));
}

function verifyDirectory(source, dest, successCallback) {
    getDirectoryEntries(source, function(sourceEntries) {
        getDirectoryEntries(dest, function(destEntries) {
            sourceEntries.sort();
            destEntries.sort();
            test(sourceEntries.length, destEntries.length);
            var verifyOne = function(index) {
                verifyFile(sourceEntries[index], destEntries[index], function() {
                    if (index >= sourceEntries.length) {
                        successCallback();
                        return;
                    }
                    verifyOne(index + 1);
                });
            };
            verifyOne(0);
        });
    });
}

function getDirectoryEntries(entry, entriesCallback) {
    var allEntries = [];
    var addEntries = function(entries, continueCallback) {
        if (entries.length == 0) {
            entriesCallback(allEntries);
            return;
        }
        allEntries.concat(entries);
        if (entries.length != 0) continueCallback();
    };
    var entriesCallback = function(entries) {
        addEntries(entries, successCallback, function() {
            reader.readDirectory(entriesCallback);
        });
    };
    var reader = entry.createReader();
    reader.readDirectory(entriesCallback, errorCallback('readDirectory: ' + entry.fullPath));
}

function cleanupDirectory(directory, successCallback) {
    directory.removeRecursively(
        successCallback,
        errorCallback('removeRecursively:' + directory.fullPath));
}

function resetDirectory(directory, successCallback) {
    var fs = directory.filesystem;
    var path = directory.fullPath;
    cleanupDirectory(directory, function() {
        fs.root.getDirectory(path, {create:true},
                             function () {
                                log(fs.name + ': reset ' + path);
                                successCallback();
                             }, errorCallback('getDirectory(create):' + path));
    });
}

function setupFiles(root, index, successCallback)
{
    if (index >= testFiles.length) {
        successCallback();
        return;
    }
    var file = testFiles[index];
    var msg = 'create testFiles[' + index + ']: ' + file.path;
    var callback = function(entry) { setupFiles(root, index + 1, successCallback); };
    if (file.directory) {
        root.getDirectory(destDirectoryPath + '/' + file.path, {create:true}, callback, errorCallback(msg));
        return;
    }

    root.getFile(file.path, {create:true}, function(entry) {
        entry.createWriter(function (writer) {
            writer.truncate(file.size);
            writer.onerror = errorCallback('truncate ' + entry.fullPath);
            writer.onwriteend = callback;
        }, errorCallback('create writer for ' + entry.fullPath));
    }, errorCallback(msg));
}

function startTest(e) {
    e.stopPropagation(e);
    e.preventDefault();

    log('Verifying contents of DataTransferItems...');
    var items = e.dataTransfer.items;
    test(1, items.length);
    test('file', items[0].kind);

    var entry = items[0].webkitGetAsEntry();
    test(true, entry.isDirectory);
    sourceTestDirectory = entry;
    setupDestFileSystem(function() {
        log('Successfully setup test environment.');
        runTests(0, function() {
            log('Successfully ran ' + tests.length + ' tests.');
            cleanupDirectory(destTestDirectory, function() {
                log('Cleanup done.');
                if (window.testRunner)
                    testRunner.notifyDone();
            });
        });
    });
}

var destination = document.getElementById('destination');
destination.addEventListener('dragover', function(e) {
    e.stopPropagation();
    e.preventDefault();
}, false);
destination.addEventListener('drop', startTest, false);

if (window.testRunner) {
    testRunner.waitUntilDone();
    testRunner.dumpAsText();

    eventSender.beginDragWithFiles([sourceDirectoryPath]);
    eventSender.leapForward(100);
    eventSender.mouseMoveTo(destination.offsetLeft + 10, destination.offsetTop + destination.offsetHeight / 2);
    eventSender.mouseUp();
}

</script>
</body>
</html>
